import hashlib

import pytest
from botocore import retryhandler, stub
from botocore.args import ClientArgsCreator
from botocore.awsrequest import AWSResponse
from botocore.client import BaseClient, ClientCreator, Config
from botocore.configprovider import SmartDefaultsConfigStoreFactory
from botocore.context import start_as_current_context, with_current_context
from botocore.credentials import (
    AssumeRoleCredentialFetcher,
    AssumeRoleProvider,
    AssumeRoleWithWebIdentityCredentialFetcher,
    AssumeRoleWithWebIdentityProvider,
    BotoProvider,
    CachedCredentialFetcher,
    CanonicalNameCredentialSourcer,
    ConfigProvider,
    ContainerProvider,
    CredentialResolver,
    Credentials,
    DeferredRefreshableCredentials,
    EnvProvider,
    InstanceMetadataProvider,
    LoginCredentialFetcher,
    LoginProvider,
    OriginalEC2Provider,
    ProcessProvider,
    ProfileProviderBuilder,
    RefreshableCredentials,
    SharedCredentialProvider,
    SSOCredentialFetcher,
    SSOProvider,
    _get_client_creator,
    create_credential_resolver,
    create_mfa_serial_refresher,
    get_credentials,
)
from botocore.discovery import (
    EndpointDiscoveryHandler,
    EndpointDiscoveryManager,
)
from botocore.endpoint import (
    Endpoint,
    EndpointCreator,
    convert_to_response_dict,
)
from botocore.eventstream import EventStream
from botocore.handlers import (
    check_for_200_error,
    inject_presigned_url_ec2,
    inject_presigned_url_rds,
    parse_get_bucket_location,
)
from botocore.hooks import EventAliaser, HierarchicalEmitter
from botocore.httpchecksum import (
    AwsChunkedWrapper,
    StreamingChecksumBody,
    _apply_request_trailer_checksum,
    _handle_bytes_response,
    _handle_streaming_response,
    apply_request_checksum,
    handle_checksum_body,
)
from botocore.httpsession import URLLib3Session
from botocore.paginate import PageIterator, ResultKeyIterator
from botocore.parsers import (
    PROTOCOL_PARSERS,
    BaseRpcV2Parser,
    EC2QueryParser,
    JSONParser,
    QueryParser,
    ResponseParser,
    ResponseParserFactory,
    RestJSONParser,
    RestXMLParser,
    RpcV2CBORParser,
    create_parser,
)
from botocore.regions import EndpointRulesetResolver
from botocore.response import StreamingBody, get_response
from botocore.retries import adaptive, special, standard
from botocore.retries.bucket import TokenBucket
from botocore.session import Session, get_session
from botocore.signers import (
    RequestSigner,
    S3PostPresigner,
    _dsql_generate_db_auth_token,
    add_dsql_generate_db_auth_token_methods,
    add_generate_db_auth_token,
    add_generate_presigned_post,
    add_generate_presigned_url,
    dsql_generate_db_connect_admin_auth_token,
    dsql_generate_db_connect_auth_token,
    generate_db_auth_token,
    generate_presigned_post,
    generate_presigned_url,
)
from botocore.tokens import (
    DeferredRefreshableToken,
    SSOTokenProvider,
    create_token_resolver,
)
from botocore.utils import (
    ContainerMetadataFetcher,
    IdentityCache,
    IMDSFetcher,
    IMDSRegionProvider,
    InstanceMetadataFetcher,
    InstanceMetadataRegionFetcher,
    S3ExpressIdentityCache,
    S3ExpressIdentityResolver,
    S3RegionRedirector,
    S3RegionRedirectorv2,
    create_nested_client,
)
from botocore.waiter import (
    NormalizedOperationMethod,
    Waiter,
    create_waiter_with_client,
)
from dill.source import getsource

# This file ensures that our private patches will work going forward.  If a
# method gets updated this will assert and someone will need to validate:
# 1) If our code needs to be updated
# 2) If our minimum botocore version needs to be updated
# 3) If we need to replace the below hash (not backwards compatible) or add
#    to the set

# These are guards to our main patches

# !!! README: HOW TO UPDATE THESE !!!
# -----------------------------------
# (tests break with new version of aiohttp/botocore)
#
# 1) Adding support for more versions of aiohttp/botocore
#    In this scenario you need to ensure that aiobotocore supports the changes
#    that broke these tests along with the old versions of the libraries
#    and APPEND to the set of hashes that we support for each object you
#    validated.
# 2) Bumping up the base version of aiohttp/botocore that we support
#    In this scenario ensure aiobotocore supports the new version of the libs
#    and REPLACE all entries with the current hashes with the new libs.

# REPLACE = backwards incompatible change
# APPEND = officially supporting more versions of botocore/aiohttp

_PROTOCOL_PARSER_CONTENT = {
    'ec2',
    'query',
    'json',
    'rest-json',
    'rest-xml',
    'smithy-rpc-v2-cbor',
}


def test_protocol_parsers():
    # Check that no new parsers have been added
    current_parsers = set(PROTOCOL_PARSERS.keys())
    assert current_parsers == _PROTOCOL_PARSER_CONTENT


@pytest.mark.parametrize(
    "obj, digests",
    [
        # If you're changing these, most likely need to update dependencies in pyproject.toml as well.
        # args.py
        (
            ClientArgsCreator.get_client_args,
            {
                '3dfe4ed858d06ca35b5033c0f5dc9531e12090c2',
            },
        ),
        (
            ClientArgsCreator._build_endpoint_resolver,
            {
                '354033a66f90fc1d939a3309ae7d595d480020a6',
            },
        ),
        # client.py
        (
            ClientCreator.create_client,
            {
                '1c27be7d1b4374887620be970dca01a9fecf9632',
            },
        ),
        (
            ClientCreator._create_client_class,
            {
                'fcecaf8d4f2c1ac3c5d0eb50c573233ef86d641d',
                '320c74206570605ff55ca32535b3f6108a7d8c1f',
            },
        ),
        (
            ClientCreator._register_endpoint_discovery,
            {
                '483c6c8e035810d1b76110fc1956de76943c2f18',
            },
        ),
        (
            ClientCreator._get_client_args,
            {
                'd5e19b1e62f64a745de842963c2472825a66e854',
            },
        ),
        (
            ClientCreator._register_s3express_events,
            {
                '716c1549989eef6bbd048bf4f134c1b4659e124a',
            },
        ),
        (
            ClientCreator._register_s3_events,
            {
                '4ab15da7cb36fa795f64154581a970b0966fdf50',
            },
        ),
        (
            ClientCreator._register_retries,
            {
                'ceecfc40a4ffa83551d7e6f63fd5d17f820664b0',
            },
        ),
        (
            ClientCreator._register_v2_adaptive_retries,
            {
                '665ecd77d36a5abedffb746d83a44bb0a64c660a',
            },
        ),
        (
            ClientCreator._register_v2_standard_retries,
            {
                '9ec4ff68599544b4f46067b3783287862d38fb50',
            },
        ),
        (
            ClientCreator._register_legacy_retries,
            {
                '000b2f2a122602e2e741ec2e89308dc2e2b67329',
                '06864c8ecac153fa36d9d57f0057cb95909ee7cd',
            },
        ),
        (
            BaseClient._make_api_call.__wrapped__,
            {
                '44a1fbef21dc588a7976510c3540c5a51350aa11',
            },
        ),
        (
            BaseClient._make_request,
            {
                'cfd8bbf19ea132134717cdf9c460694ddacdbf58',
                'bdfa0e9843e97bee2da16f17c6a7685ad4a0a44b',
            },
        ),
        (
            BaseClient._convert_to_request_dict,
            {
                '5e0a374926b6ee1a8715963ab551e126506e7fc9',
            },
        ),
        (
            BaseClient._emit_api_params,
            {
                'abd67874dae8d5cd2788412e4699398cb915a119',
            },
        ),
        (
            BaseClient._resolve_endpoint_ruleset,
            {
                'f09731451ff6ba0645dc82e5c7948dfbf781e025',
            },
        ),
        (
            BaseClient.get_paginator,
            {
                '1c38079de68ccd43a5a06e36b1a47ec62233a7c2',
            },
        ),
        (
            BaseClient.get_waiter,
            {
                '4a4aeabe53af25d3737204187a31f930230864b4',
                '40484242690c0679c3b13fddf0d6c9a26f7b25d2',
            },
        ),
        (
            BaseClient.__getattr__,
            {
                '3ec17f468f50789fa633d6041f40b66a2f593e77',
            },
        ),
        # config.py
        (
            Config.merge,
            {
                'c3dd8c3ffe0da86953ceba4a35267dfb79c6a2c8',
            },
        ),
        (
            Config,
            {
                'da2d8b797568604449695cdcf803e344bdf887eb',
                'a3abd6cb69883934f48403acfaa5ef598c548982',
            },
        ),
        # context.py
        (
            with_current_context,
            {'674c6120c400c7b4b2eba2aa8167ed90ac884eb2'},
        ),
        (
            start_as_current_context.__wrapped__,
            {'b9e5e8a4e48457f868c4397172fe8202bd918e18'},
        ),
        # credentials.py
        (
            create_mfa_serial_refresher,
            {
                '9b5e98782fcacdcea5899a6d0d29d1b9de348bb0',
            },
        ),
        (
            Credentials.get_frozen_credentials,
            {
                '87ced1e435eda7738852e0569ddbff3b7a8e977f',
            },
        ),
        (
            RefreshableCredentials.__init__,
            {
                '88ab16aa041eb1cad8d666834613cbe5f0cf7514',
            },
        ),
        # We've overridden some properties
        (
            RefreshableCredentials.__dict__['access_key'].fset,
            {
                'edc4a25baef877a9662f68cd9ccefcd33a81bab7',
            },
        ),
        (
            RefreshableCredentials.__dict__['access_key'].fget,
            {
                'f6c823210099db99dd343d9e1fae6d4eb5aa5fce',
            },
        ),
        (
            RefreshableCredentials.__dict__['secret_key'].fset,
            {
                'b19fe41d66822c72bd6ae2e60de5c5d27367868a',
            },
        ),
        (
            RefreshableCredentials.__dict__['secret_key'].fget,
            {
                '3e27331a037549104b8669e225bbbb2c465a16d4',
            },
        ),
        (
            RefreshableCredentials.__dict__['token'].fset,
            {
                '1f8a308d4bf21e666f8054a0546e91541661da7b',
            },
        ),
        (
            RefreshableCredentials.__dict__['token'].fget,
            {
                '005c1b44b616f37739ce9276352e4e83644d8220',
            },
        ),
        (
            RefreshableCredentials.__dict__['account_id'].fset,
            {
                '0d67de1c18dc80429b8537fe94a842175636f850',
            },
        ),
        (
            RefreshableCredentials.__dict__['account_id'].fget,
            {
                'd40a5f4571df3a239500a615ca0cc3fe77ac70ab',
            },
        ),
        (
            RefreshableCredentials._refresh,
            {
                'd5731d01db2812d498df19b4bd5d7c17519241fe',
            },
        ),
        (
            RefreshableCredentials._protected_refresh,
            {
                '8b2d523a605a4f4728ad99861c14143838e56176',
            },
        ),
        (
            RefreshableCredentials.get_frozen_credentials,
            {
                'f661c84a8b759786e011f0b1e8a468a0c6294e36',
            },
        ),
        (
            DeferredRefreshableCredentials.__init__,
            {
                'dd5ccda2b047854ae5e88907b654b57d35fe0dfd',
            },
        ),
        (
            SSOCredentialFetcher._get_credentials,
            {
                '6fdbe9d6045e98be5125fade72fb1711936666b0',
            },
        ),
        (
            SSOProvider.load,
            {
                'ca09b93ac1aea3df424652536d70f0fc52d86937',
            },
        ),
        (
            LoginCredentialFetcher.refresh_credentials,
            {
                '059e31ce9f0ec8b78a9fa813272ee9d241c182ef',
            },
        ),
        (
            LoginProvider.load,
            {
                '282680f216dd21a68c165dd36d16cbcaaae7bf2a',
            },
        ),
        (
            CachedCredentialFetcher._get_credentials,
            {
                '02a7d13599d972e3f258d2b53f87eeda4cc3e3a4',
            },
        ),
        (
            CachedCredentialFetcher.fetch_credentials,
            {
                '0dd2986a4cbb38764ec747075306a33117e86c3d',
            },
        ),
        (
            CachedCredentialFetcher._get_cached_credentials,
            {
                'f578b2527712d501c021f8236bd20e68e99201f5',
            },
        ),
        (
            AssumeRoleCredentialFetcher._get_credentials,
            {
                '7216e35a401c7bd95f8d95d872f55590ade8aaa7',
            },
        ),
        (
            AssumeRoleCredentialFetcher._create_client,
            {
                '27c76f07bd43e665899ca8d21b6ba2038b276fbb',
            },
        ),
        # Referenced by AioAssumeRoleWithWebIdentityCredentialFetcher
        (
            AssumeRoleWithWebIdentityCredentialFetcher.__init__,
            {
                'ab270375dfe425c5e21276590dea690fdbfe40a5',
            },
        ),
        (
            AssumeRoleWithWebIdentityCredentialFetcher._get_credentials,
            {
                '726f644df3f8e71125c8890193f2fa25bd22e331',
            },
        ),
        (
            AssumeRoleWithWebIdentityCredentialFetcher._assume_role_kwargs,
            {
                '8fb4fefe8664b7d82a67e0fd6d6812c1c8d92285',
            },
        ),
        # Ensure that the load method doesn't do anything we should asyncify
        (
            EnvProvider.load,
            {
                'da0cfb81a7a27ac1159c9b87920908944d1849f2',
            },
        ),
        (
            ContainerProvider.__init__,
            {
                'ea6aafb2e12730066af930fb5a27f7659c1736a1',
            },
        ),
        (
            ContainerProvider.load,
            {
                '57c35569050b45c1e9e33fcdb3b49da9e342fdcf',
            },
        ),
        (
            ContainerProvider._retrieve_or_fail,
            {
                '057ebdc912f15ec4903ab2e157f339d2ae740615',
            },
        ),
        (
            ContainerProvider._create_fetcher,
            {
                'f70e2b62a83099aa9863ed31fae7416b8a4c8df5',
            },
        ),
        (
            InstanceMetadataProvider.load,
            {
                '8b32da46500dd7b7177e1e6f781a7ce962dd3b66',
            },
        ),
        (
            ProfileProviderBuilder._create_process_provider,
            {
                'c5eea47bcfc449a6d73a9892bd0e1897f6be0c20',
            },
        ),
        (
            ProfileProviderBuilder._create_shared_credential_provider,
            {
                '33f99c6a0ef71a92b0c52ccc59c8ca7e33fa0890',
            },
        ),
        (
            ProfileProviderBuilder._create_config_provider,
            {
                'f9a40d4211f6e663ba2ae9682fba5306152178c5',
            },
        ),
        (
            ProfileProviderBuilder._create_web_identity_provider,
            {
                '478745fa6779a7c69fe9441d89d3e921438e3a59',
            },
        ),
        (
            ProfileProviderBuilder._create_sso_provider,
            {
                'e463160179add7a1a513e46ee848447a216504aa',
            },
        ),
        (
            ProfileProviderBuilder._create_login_provider,
            {
                '4bf3a53db99700f0dee84d02470d2a52a8ad5ca8',
            },
        ),
        (
            ConfigProvider.load,
            {
                'af1d9e127b3d40376570cb48e3cbc8d66dff2041',
            },
        ),
        (
            SharedCredentialProvider.load,
            {
                'fddbf6610526a41358187a529dbd2c2b82e23224',
            },
        ),
        (
            ProcessProvider.__init__,
            {
                '2e870ec0c6b0bc8483fa9b1159ef68bbd7a12c56',
            },
        ),
        (
            ProcessProvider.load,
            {
                'dd8c5de56d32dd05f4e664faac84979ea84086cc',
            },
        ),
        (
            ProcessProvider._retrieve_credentials_using,
            {
                'd8755c0bb80c4c9852c89276db6ec418f988f6f0',
            },
        ),
        (
            CredentialResolver.load_credentials,
            {
                'ef31ba8817f84c1f61f36259da1cc6e597b8625a',
            },
        ),
        (
            AssumeRoleWithWebIdentityProvider.load,
            {
                '8f48f6cadf08a09cf5a22b1cc668e60bc4ea389d',
            },
        ),
        (
            AssumeRoleWithWebIdentityProvider._assume_role_with_web_identity,
            {
                '90c6a54d339f439988856f439dbaea9f371202f7',
            },
        ),
        (
            AssumeRoleProvider.load,
            {
                'ee9ddb43e25eb1105185253c0963a2f5add49a95',
            },
        ),
        (
            AssumeRoleProvider._load_creds_via_assume_role,
            {
                'bc9c38d6320b5f9712570ec8570f467e5288340d',
            },
        ),
        (
            AssumeRoleProvider._resolve_source_credentials,
            {
                '1c2018d648dc72ab165cd1ffe1adc6b65856aa6b',
            },
        ),
        (
            AssumeRoleProvider._resolve_credentials_from_profile,
            {
                'a5a2808e315b45957cb881b31b73624eba44ade6',
            },
        ),
        (
            AssumeRoleProvider._resolve_static_credentials_from_profile,
            {
                'a470795f6ba451cf99ce7456fef24777f8087654',
            },
        ),
        (
            AssumeRoleProvider._resolve_credentials_from_source,
            {
                'b3144366432c11cee4bca286bd5ff10c3449b97b',
            },
        ),
        (
            CanonicalNameCredentialSourcer.source_credentials,
            {
                '602930a78e0e64e3b313a046aab5edc3bcf5c2d9',
            },
        ),
        (
            CanonicalNameCredentialSourcer._get_provider,
            {
                'c028b9776383cc566be10999745b6082f458d902',
            },
        ),
        (
            BotoProvider.load,
            {
                'c85411fa3d3ff75b3edb98f38c36426c0ffed3bb',
            },
        ),
        (
            OriginalEC2Provider.load,
            {
                'dc58cd1c79d177105b183a2d20e1154e6f8f0733',
            },
        ),
        (
            create_credential_resolver,
            {
                'fe797afd33126be87f86e44ab20475d50d727a4e',
            },
        ),
        (
            get_credentials,
            {
                'ff0c735a388ac8dd7fe300a32c1e36cdf33c0f56',
            },
        ),
        (
            _get_client_creator,
            {
                '6274e5675ecf13180b5a18daa0242bb71d6437b6',
            },
        ),
        # configprovider.py
        (
            SmartDefaultsConfigStoreFactory.merge_smart_defaults,
            {
                'e320299bb739694fefe2f5df6be62cc5321d3dc5',
            },
        ),
        (
            SmartDefaultsConfigStoreFactory.resolve_auto_mode,
            {
                '013fa8904b42931c69e3d8623025a1582379ba2a',
            },
        ),
        # endpoint.py
        (
            convert_to_response_dict,
            {
                '5b7701c1f5b3cb2daa6eb307cdbdbbb2e9d33e5f',
                '0fb9d2f2ab899fad8b2be93223b403f11032670a',
            },
        ),
        (
            Endpoint.__init__,
            {
                '4bafe9733a02817950f5096612410ec4ebc40f55',
            },
        ),
        (
            Endpoint.create_request,
            {
                '37d0fbd02f91aef6c0499a2d0a725bf067c3ce8b',
                'f78944c88453219ed3f0f5c8eefccdc69faf3046',
            },
        ),
        (
            Endpoint._send_request,
            {
                '5d40748a95c3005728e6548b402b90cb57d6f575',
                '0158d0b6c492fde95947b49c34fd0927e5d145a1',
            },
        ),
        (
            Endpoint._get_response,
            {
                'bbf10e6e07147d50e09d7205bf0883bd673a8bf3',
            },
        ),
        (
            Endpoint._do_get_response,
            {
                'a9f3ae0f375ba9967425b1fb3e4d45537df4f1e3',
            },
        ),
        (
            Endpoint._needs_retry,
            {
                'f718e2ff874763a677648fe6f87cc65e4cec2792',
            },
        ),
        (
            Endpoint._send,
            {
                '644c7e5bb88fecaa0b2a204411f8c7e69cc90bf1',
            },
        ),
        (
            Endpoint._add_modeled_error_fields,
            {
                'd0390647f2d7a4a325be048dcda4dcc7f42fdd17',
            },
        ),
        (
            EndpointCreator.create_endpoint,
            {
                '863e17b1299f9fda2cef5be3297d470d1bfa86ae',
                'a49253f3c80fc69f66fd64c8549f6daa47f7c6ad',
            },
        ),
        # eventstream.py
        (
            EventStream._create_raw_event_generator,
            {
                '1764be20b3abe19b60381756a989794de298ffbb',
            },
        ),
        (
            EventStream.__iter__,
            {
                '8a9b454943f8ef6e81f5794d641adddd1fdd5248',
            },
        ),
        (
            EventStream._parse_event,
            {
                'c5b4e65fe718653a6f4cee4e8647f286f10fae05',
            },
        ),
        (
            EventStream.get_initial_response,
            {
                'aed648305970c90bb5d1e31f6fe5ff12cf6a2a06',
            },
        ),
        # hooks.py
        (
            HierarchicalEmitter._emit,
            {
                '5d9a6b1aea1323667a9310e707a9f0a006f8f6e8',
            },
        ),
        (
            HierarchicalEmitter.emit_until_response,
            {
                '23670e04e0b09a9575c7533442bca1b2972ade82',
            },
        ),
        (
            HierarchicalEmitter._verify_and_register,
            {
                '41eda968127e35e02e7120ec621240b61639e3dd',
            },
        ),
        (
            EventAliaser.emit_until_response,
            {
                '0d635bf7ae5022b1fdde891cd9a91cd4c449fd49',
            },
        ),
        # paginate.py
        (
            PageIterator.__iter__,
            {
                '0bfe2ffb0ea63faa1f28cc22250ce626959d05d1',
            },
        ),
        (
            PageIterator._make_request,
            {
                'e926671018897ac5851a3add5d2bc15a2d6142df',
            },
        ),
        (
            PageIterator.result_key_iters,
            {
                'e8cd36fdc4960e08c9aa50196c4e5d1ee4e39756',
            },
        ),
        (
            PageIterator.build_full_result,
            {
                '9051327d350ed5a4843c74d34be74ba2f1732e30',
            },
        ),
        (
            ResultKeyIterator,
            {
                '3028dde4c4de6029f628f4a9d1fff36986b41591',
            },
        ),
        # parsers.py
        (
            ResponseParserFactory.create_parser,
            {
                '5cf11c9acecd1f60a013f6facbe0f294daa3f390',
            },
        ),
        (
            ResponseParser.parse,
            {
                'c2153eac3789855f4fc6a816a1f30a6afe0cf969',
            },
        ),
        (
            ResponseParser._create_event_stream,
            {
                '0564ba55383a71cc1ba3e5be7110549d7e9992f5',
            },
        ),
        (
            RestXMLParser._create_event_stream,
            {
                '0564ba55383a71cc1ba3e5be7110549d7e9992f5',
            },
        ),
        (
            EC2QueryParser._create_event_stream,
            {
                '0564ba55383a71cc1ba3e5be7110549d7e9992f5',
            },
        ),
        (
            QueryParser._create_event_stream,
            {
                '0564ba55383a71cc1ba3e5be7110549d7e9992f5',
            },
        ),
        (
            JSONParser._create_event_stream,
            {
                '0564ba55383a71cc1ba3e5be7110549d7e9992f5',
            },
        ),
        (
            JSONParser._do_parse,
            {
                '9c3d5832e6c55a87630128cc8b9121579ef4a708',
            },
        ),
        (
            JSONParser._handle_event_stream,
            {
                '3cf7bb1ecff0d72bafd7e7fd6625595b4060abd6',
            },
        ),
        (
            BaseRpcV2Parser._do_parse,
            {
                'e2d884a116d830f57c5ca41f315d3baac49372eb',
            },
        ),
        (
            RestJSONParser._create_event_stream,
            {
                '0564ba55383a71cc1ba3e5be7110549d7e9992f5',
            },
        ),
        (
            RpcV2CBORParser.EVENT_STREAM_PARSER_CLS,
            {
                '10c1f773f07e22929ecac791729c1a30a4091bd3',
            },
        ),
        (
            RpcV2CBORParser._handle_event_stream,
            {
                '2aa007aaca55b37c7e327b7ef8c86237f19690cc',
            },
        ),
        (
            create_parser,
            {
                '37e9f1c3b60de17f477a9b79eae8e1acaa7c89d7',
            },
        ),
        # regions.py
        (
            EndpointRulesetResolver.construct_endpoint,
            {
                '05e4f37e807b57bf9ff37dbe870308b684c62c02',
            },
        ),
        (
            EndpointRulesetResolver._get_provider_params,
            {
                '8f4b9bd22516c9f00fc6655923312f415268c8c4',
            },
        ),
        (
            EndpointRulesetResolver._get_customized_builtins,
            {
                '41085e0e1ac19915c24339f25b8d966708905fd0',
                '51f00c9f658df0cd0e140aaed24b517954f9300c',
            },
        ),
        # response.py
        (
            StreamingBody,
            {
                'e358f72191c4c1cb37d8fe90871342abf79afde2',
            },
        ),
        (
            get_response,
            {
                'ea8686ae71fae32410e2f1774e5774d6715dd492',
            },
        ),
        # session.py
        (
            Session.__init__,
            {
                'c796153d589ea6fe46a3a1afa2c460f06a1c37a2',
            },
        ),
        (
            Session._register_response_parser_factory,
            {
                'bb8f7f3cc4d9ff9551f0875604747c4bb5030ff6',
            },
        ),
        (
            Session.create_client,
            {
                'c796153d589ea6fe46a3a1afa2c460f06a1c37a2',
            },
        ),
        (
            Session._create_token_resolver,
            {
                '142df7a219db0dd9c96fd81dc9e84a764a2fe5fb',
            },
        ),
        (
            Session._create_credential_resolver,
            {
                '87e98d201c72d06f7fbdb4ebee2dce1c09de0fb2',
            },
        ),
        (
            Session.set_credentials,
            {
                '923e96e9386054d65b38a3871574dd32c0f5015f',
            },
        ),
        (
            Session.get_credentials,
            {
                '718da08b630569e631f93aedd65f1d9215bfc30b',
            },
        ),
        (
            get_session,
            {
                'c47d588f5da9b8bde81ccc26eaef3aee19ddd901',
            },
        ),
        (
            Session.get_service_data,
            {
                '3879b969c0c2b1d5b454006a1025deb4322ae804',
                'c6b755f2eff7277ccc6023552d306ff823280404',
            },
        ),
        (
            Session.get_service_model,
            {
                '1c8f93e6fb9913e859e43aea9bc2546edbea8365',
            },
        ),
        (
            Session.get_available_regions,
            {
                '9fb4df0b7d082a74d524a4a15aaf92a2717e0358',
            },
        ),
        (
            Session._register_smart_defaults_factory,
            {
                'af5fc9cf6837ed119284603ca1086e4113febec0',
            },
        ),
        # signers.py
        (
            RequestSigner.handler,
            {
                '371909df136a0964ef7469a63d25149176c2b442',
            },
        ),
        (
            RequestSigner.sign,
            {
                '2f1f45a6fcfcca1be2c5e292c9e1b80453e7fa57',
                'deb7af66bc099801810eee5b00db83da2563d0a3',
            },
        ),
        (
            RequestSigner.get_auth,
            {
                '13e90d57d536179621ac012ace97e4c2cbaa096e',
            },
        ),
        (
            RequestSigner.get_auth_instance,
            {
                '13e90d57d536179621ac012ace97e4c2cbaa096e',
            },
        ),
        (
            RequestSigner._choose_signer,
            {
                'bd0e9784029b8aa182b5aec73910d94cb67c36b0',
                '23861aeaf48509e59c131547d98cdeb4fc4af1d3',
            },
        ),
        (
            RequestSigner.generate_presigned_url,
            {
                '417682868eacc10bf4c65f3dfbdba7d20d9250db',
            },
        ),
        (
            add_generate_presigned_url,
            {
                '5820f74ac46b004eb79e00eea1adc467bcf4defe',
            },
        ),
        (
            generate_presigned_url,
            {
                'd03631d6810e2453b8874bc76619927b694a4207',
            },
        ),
        (
            S3PostPresigner.generate_presigned_post,
            {
                '01c61dc0f33392a19def738afc634f5def401e32',
            },
        ),
        (
            add_generate_presigned_post,
            {
                'e30360f2bd893fabf47f5cdb04b0de420ccd414d',
            },
        ),
        (
            generate_presigned_post,
            {
                'a3a834a08be2cf76c20ea137ba6b28e7a12f58ed',
                'd93240c58dcda7b63cf2b7144ee0fea110f0e762',
            },
        ),
        (
            add_generate_db_auth_token,
            {
                'f61014e6fac4b5c7ee7ac2d2bec15fb16fa9fbe5',
            },
        ),
        (
            generate_db_auth_token,
            {
                '1f37e1e5982d8528841ce6b79f229b3e23a18959',
            },
        ),
        (
            add_dsql_generate_db_auth_token_methods,
            {
                '95c68a1aac8ee549e11b5dc010b6bb03f9ea00ea',
            },
        ),
        (
            _dsql_generate_db_auth_token,
            {
                '53034b0475122209509db59fbd79a4ead70836cf',
            },
        ),
        (
            dsql_generate_db_connect_auth_token,
            {
                '29b5919b695113c55452f2325d0ff66dd719a647',
            },
        ),
        (
            dsql_generate_db_connect_admin_auth_token,
            {
                'd7e7a4899b8fd3a544dd1df95196517e2cfd5c84',
            },
        ),
        # tokens.py
        (
            create_token_resolver,
            {
                '7e502da18a02d4f0224568041e3a7ef6a67b2de8',
            },
        ),
        (
            DeferredRefreshableToken.__init__,
            {
                '199254ed7e211119bdebf285c5d9a9789f6dc540',
            },
        ),
        (
            DeferredRefreshableToken.get_frozen_token,
            {
                '846a689a25550c63d2a460555dc27148abdcc992',
            },
        ),
        (
            DeferredRefreshableToken._refresh,
            {
                '92af1e549b5719caa246a81493823a37a684d017',
            },
        ),
        (
            DeferredRefreshableToken._protected_refresh,
            {
                'bd5c1911626e420005e0e60d583a73c68925f4b6',
            },
        ),
        (
            SSOTokenProvider._attempt_create_token,
            {
                '9cf7b75618a253d585819485e5da641cef129d46',
            },
        ),
        (
            SSOTokenProvider._refresh_access_token,
            {
                '6263c009e6d86011ca1226d61ea95163bbfca258',
            },
        ),
        (
            SSOTokenProvider._refresher,
            {
                'd89b3446344826e5b740840c12fd9279810c45d2',
            },
        ),
        (
            SSOTokenProvider.load_token,
            {
                'fb9114c12952ba47b50e201057e3f5664abdb9d8',
            },
        ),
        # utils.py
        (
            ContainerMetadataFetcher.__init__,
            {
                '46d90a7249ba8389feb487779b0a02e6faa98e57',
            },
        ),
        (
            ContainerMetadataFetcher.retrieve_full_uri,
            {
                '2c7080f7d6ee5a3dacc1b690945c045dba1b1d21',
            },
        ),
        (
            ContainerMetadataFetcher.retrieve_uri,
            {
                '9067ffe122e6fcff4a7f4dd2b7f5b3de5e1ea4ec',
            },
        ),
        (
            ContainerMetadataFetcher._retrieve_credentials,
            {
                'b00694931af86ef1a9305ad29328030ee366cea9',
            },
        ),
        (
            ContainerMetadataFetcher._get_response,
            {
                'b2c2fe2d74ce1894168e8e052c4e97cc70539b1a',
            },
        ),
        (
            IMDSFetcher.__init__,
            {
                '50ea982d3b94d7301d39480f827cfc1502800cb4',
            },
        ),
        (
            IMDSFetcher._get_request,
            {
                '118354ef768da5a7402d5d2bf6f55b4fbb2525e4',
            },
        ),
        (
            IMDSFetcher._fetch_metadata_token,
            {
                '12225b35a73130632038785a8c2e6fbaaf9de1f4',
            },
        ),
        (
            IMDSFetcher._default_retry,
            {
                '362ce5eff50bfb74e58fbdd3f44146a87958318a',
            },
        ),
        (
            IMDSFetcher._is_non_ok_response,
            {
                '448b80545b1946ec44ff19ebca8d4993872a6281',
            },
        ),
        (
            IMDSFetcher._is_empty,
            {
                '241b141c9c352a4ef72964f8399d46cbe9a5aebc',
            },
        ),
        (
            IMDSFetcher._log_imds_response,
            {
                'dcbe619ce2ddb8b5015f128612d86dd8a5dd31e8',
            },
        ),
        (
            InstanceMetadataFetcher.retrieve_iam_role_credentials,
            {
                '40f31ba06abb9853c2e6fea68846742bd3eda919',
            },
        ),
        (
            InstanceMetadataFetcher._get_iam_role,
            {
                '80073d7adc9fb604bc6235af87241f5efc296ad7',
            },
        ),
        (
            InstanceMetadataFetcher._get_credentials,
            {
                '1a64f59a3ca70b83700bd14deeac25af14100d58',
            },
        ),
        (
            InstanceMetadataFetcher._is_invalid_json,
            {
                '97818b51182a2507c99876a40155adda0451dd82',
            },
        ),
        (
            InstanceMetadataFetcher._needs_retry_for_role_name,
            {
                'ca9557fb8e58d03e09d77f9fb63d21afb4689b58',
            },
        ),
        (
            InstanceMetadataFetcher._needs_retry_for_credentials,
            {
                'e7e5a8ce541110eb79bf98414171d3a1c137e32b',
            },
        ),
        (
            S3RegionRedirectorv2.redirect_from_error,
            {
                '2a715115e94bddcea4cce936bf7c7013f1f6ecdf',
            },
        ),
        (
            S3RegionRedirectorv2.get_bucket_region,
            {
                'b5bbc8b010576668dc2812d657c4b48af79e8f99',
            },
        ),
        (
            S3RegionRedirector.redirect_from_error,
            {
                '5db904d0311db5c875aed0f6a78278f173ca40a7',
            },
        ),
        (
            S3RegionRedirector.get_bucket_region,
            {
                'b5bbc8b010576668dc2812d657c4b48af79e8f99',
            },
        ),
        (
            InstanceMetadataRegionFetcher.retrieve_region,
            {
                '0134024f0aa2d2b49ec436ea8058c1eca8fac4af',
            },
        ),
        (
            InstanceMetadataRegionFetcher._get_region,
            {
                '16e8fc546958471650eef233b0fd287758293019',
            },
        ),
        (
            IMDSRegionProvider.provide,
            {
                '09d1b70bc1dd7a37cb9ffd437acd71283b9142e9',
            },
        ),
        (
            IMDSRegionProvider._get_instance_metadata_region,
            {
                '4631ced79cff143de5d3fdf03cd69720778f141b',
            },
        ),
        (
            IMDSRegionProvider._create_fetcher,
            {
                '18da52c786a20d91615258a8127b566688ecbb39',
            },
        ),
        (
            IdentityCache.get_credentials,
            {
                'baf98c4caaddfa0594745eb490c327c65cff8920',
            },
        ),
        (
            S3ExpressIdentityCache.get_credentials.__wrapped__,
            {
                '71f2ae5e0ea32e9bbac6f318cba963700e23b9a0',
            },
        ),
        (
            S3ExpressIdentityCache.build_refresh_callback,
            {
                '0e833cc5e30b76fa13e8caf5c024fe2a21c10f22',
            },
        ),
        (
            S3ExpressIdentityResolver.__init__,
            {
                '148a10274d3268dd42df05d3bcfb98c668f01086',
            },
        ),
        (
            create_nested_client,
            {
                '619a190d84c4871c0e3c4828b0d6ea607d8b89da',
            },
        ),
        # waiter.py
        (
            NormalizedOperationMethod.__call__,
            {
                '79723632d023739aa19c8a899bc2b814b8ab12ff',
            },
        ),
        (
            Waiter.wait,
            {
                'be33b3d947f559950943305d35daa6a8ece33ea4',
            },
        ),
        (
            create_waiter_with_client,
            {
                'e6ea06674b6fdf9157c95757a12b3c9c35af531c',
                '13d661baedd3db97e5291331ceebd4bbafaccf18',
            },
        ),
        # handlers.py
        (
            inject_presigned_url_rds,
            {
                'b5d45b339686346e81b255d4e8c36e76d3fe6a78',
            },
        ),
        (
            inject_presigned_url_ec2,
            {
                '48e09a5e4e95577e716be30f2d2706949261a07f',
            },
        ),
        (
            parse_get_bucket_location,
            {
                '64ffbf5c6aa6ebd083f49371000fa046d0de1fc6',
            },
        ),
        (
            check_for_200_error,
            {
                '3a00f0bea409528f8457d6569aecf05998094386',
            },
        ),
        # httpsession.py
        (
            URLLib3Session,
            {
                'c65ca250524de59d89a32f213f38c7403666bfef',
            },
        ),
        (
            EndpointDiscoveryHandler.discover_endpoint,
            {
                'd87eff9008356a6aaa9b7078f23ba7a9ff0c7a60',
            },
        ),
        (
            EndpointDiscoveryManager.describe_endpoint,
            {
                '2d7c40eec571a14e6e3968b710c23677ae3685e6',
            },
        ),
        (
            EndpointDiscoveryManager._refresh_current_endpoints,
            {
                'f8a51047c8f395d9458a904e778a3ac156a11911',
            },
        ),
        # retries/adaptive.py
        # See comments in AsyncTokenBucket, we completely replace the ClientRateLimiter
        # implementation from botocore.
        (
            adaptive.ClientRateLimiter,
            {
                '9dbf36d36614a4a2e2719ca7e4382aa4694caae3',
            },
        ),
        (
            adaptive.register_retry_handler,
            {
                '96c073719a3d5d41d1ca7ae5f7e31bbb431c75b3',
            },
        ),
        # retries/standard.py
        (
            standard.register_retry_handler,
            {
                'da0ae35712211bc38938e93c4af8b7aeb999084e',
                '09035248202bfd94c7ae7c532e515ec6fe2fab4b',
            },
        ),
        (
            standard.RetryHandler.needs_retry,
            {
                '89a4148d7f4af9d2795d1d0189293528aa668b59',
            },
        ),
        (
            standard.RetryPolicy.should_retry,
            {
                'b30eadcb94dadcdb90a5810cdeb2e3a0bc0c74c9',
            },
        ),
        (
            standard.StandardRetryConditions.__init__,
            {
                'e17de49a447769160964a2da926b7d72544efd48',
            },
        ),
        (
            standard.StandardRetryConditions.is_retryable,
            {
                '558a0f0b4d30f996e046779fe233f587611ca5c7',
            },
        ),
        (
            standard.OrRetryChecker.is_retryable,
            {
                '5ef0b84b1ef3a49bc193d76a359dbd314682856b',
            },
        ),
        # retries/special.py
        (
            special.RetryDDBChecksumError.is_retryable,
            {
                '6c6e0945b0989b13fd8e7d78dbfcde307a131eae',
            },
        ),
        # retries/bucket.py
        # See comments in AsyncTokenBucket, we completely replace the TokenBucket
        # implementation from botocore.
        (
            TokenBucket,
            {
                'ce932001b13e256d1a2cc625094989fff087d484',
            },
        ),
        # awsresponse.py
        (
            AWSResponse.content,
            {
                '307a4eb1d46360ef808a876d7d00cbbde6198eb1',
            },
        ),
        (
            AWSResponse.text,
            {
                'a724100ba9f6d51b333b8fe470fac46376d5044a',
            },
        ),
        # httpchecksum.py
        (
            handle_checksum_body,
            {
                'f019114f7fc3a4e200157b9689ed8a1cc9d72825',
            },
        ),
        (
            _handle_streaming_response,
            {
                '7ce971e012f9d4b04889f0af83f67281ed6a9e6e',
                '2fb57a6073db3052ca22c335e779cd991357088d',
            },
        ),
        (
            StreamingChecksumBody,
            {
                '2772706fc4f49bdd5ea810d255fc82b69451b9ac',
            },
        ),
        (
            _handle_bytes_response,
            {
                '0761c4590c6addbe8c674e40fca9f7dd375a184b',
                '11dce986975df44f08ff61d7e86cba4f92f7c19f',
            },
        ),
        (
            AwsChunkedWrapper.read,
            {
                '226db2259073a2b2e05f999e8ef55210394693d8',
            },
        ),
        (
            AwsChunkedWrapper._make_chunk,
            {
                '097361692f0fd6c863a17dd695739629982ef7e4',
            },
        ),
        (
            AwsChunkedWrapper.__iter__,
            {
                '261e26d1061655555fe3dcb2689d963e43f80fb0',
            },
        ),
        (
            apply_request_checksum,
            {
                '6d904d118cd9d768935e38a60a73a46c67a8d440',
            },
        ),
        (
            _apply_request_trailer_checksum,
            {
                '6c45ef3db14240dcaa98bd48b59076d6859c0b57',
            },
        ),
        # retryhandler.py
        (
            retryhandler.create_retry_handler,
            {
                '8fee36ed89d789194585f56b8dd4f525985a5811',
            },
        ),
        (
            retryhandler.create_checker_from_retry_config,
            {
                'bc43996b75ab9ffc7a4e8f20fc62805857867109',
            },
        ),
        (
            retryhandler._create_single_checker,
            {
                'da29339040ab1faeaf2d80752504e4f8116686f2',
            },
        ),
        (
            retryhandler._create_single_response_checker,
            {
                'dda92bb44f295a1f61750c7e1fbc176f66cb8b44',
            },
        ),
        (
            retryhandler.RetryHandler.__call__,
            {
                'e599399167b1f278e4cd839170f887d60eea5bfa',
            },
        ),
        (
            retryhandler.MaxAttemptsDecorator.__call__,
            {
                '24b442126f0ff730be0ae64dc7158929d4d2fca7',
                '631b9963bec06a9d1264bbddc3ad003ae4896945',
            },
        ),
        (
            retryhandler.MaxAttemptsDecorator._should_retry,
            {
                '581273f875bb779a9ff796df8c8597ec551abf97',
            },
        ),
        (
            retryhandler.MultiChecker.__call__,
            {
                'e8302c52e1bbbb129b6f505633a4bc4ae1e5a34f',
            },
        ),
        (
            retryhandler.CRC32Checker.__call__,
            {
                '882a731eaf6b0ddca68ab4032a169a0fa09a4d43',
            },
        ),
        (
            retryhandler.CRC32Checker._check_response,
            {
                '3ee7afd0bb1a3bf53934d77e44f619962c52b0c9',
            },
        ),
        (
            stub.Stubber,
            {
                'bccf23c3733cc656b909f5130cba80dbc9540b05',
                '7c01f505134b5ea3f4886e2288ea7f389577efd5',
                '0ff1c068779d3e8a84c4da0655cfdf5861fe1b2c',
            },
        ),
    ],
    ids=lambda x: getattr(x, "__qualname__", None),
)
def test_patches(obj, digests):
    try:
        source = getsource(obj)
    except TypeError:
        obj = obj.fget
        source = getsource(obj)

    digest = hashlib.sha1(source.encode('utf-8')).hexdigest()

    assert digest in digests
